// OPBCtrl.v
// Copyright 2006, Pico Computing, Inc.

`include "PicoDefines.v"

module OPBCtrl(
   opb_flash_en, FLASH_A, PEEKABOO, LOAD,                   //OPB flash enable and peekaboo lines
   OPB_Clk, OPB_Rst, OPB_ABus, OPB_BE, OPB_DBus,            //OPB -> Slave Signals
   OPB_RNW, OPB_select, OPB_seqAddr,
   Sl_DBus, Sl_errAck, Sl_retry, Sl_toutSup, Sl_xferAck,    //Slave -> OPB Signals
   DcmsLocked, FlashReady, StandaloneSw,
   test_pins                                                //chipscope test pins
);

parameter C_OPB_AWIDTH = 32;
parameter C_OPB_DWIDTH = 32;
parameter C_BASEADDR   = `OPB_CTRL_BASEADDR;
parameter C_HIGHADDR   = `OPB_CTRL_HIGHADDR;

output opb_flash_en;
input [25:0] FLASH_A;
output PEEKABOO;
output LOAD;

input OPB_Clk;
input OPB_Rst;
input [C_OPB_AWIDTH-1:0] OPB_ABus;
input [(C_OPB_DWIDTH/8)-1:0] OPB_BE;
input [C_OPB_DWIDTH-1:0] OPB_DBus;
input OPB_RNW;
input OPB_select;
input OPB_seqAddr;
output [C_OPB_DWIDTH-1:0] Sl_DBus;
output Sl_errAck;
output Sl_retry;
output Sl_toutSup;
output Sl_xferAck;

input DcmsLocked;
input FlashReady;
input StandaloneSw;

output [127:0] test_pins;

reg opb_flash_en;
//synthesis attribute init opb_flash_en 0;

wire opb_en = OPB_select & (OPB_ABus >= C_BASEADDR && OPB_ABus <= C_HIGHADDR);

//------ Keep our unused signals ------
// In case we need to use these later

wire opb_we = opb_en & ~OPB_RNW;
wire opb_oe = opb_en & OPB_RNW;

always @(posedge opb_we or posedge OPB_Rst) 
  begin
   if (OPB_Rst)            opb_flash_en = 0; else    //hrgt: added 6/17/05 to reset state when PC resets card.
   if (OPB_ABus[3:2] == 0) opb_flash_en = OPB_DBus[0];
  end


/* When we receive a read on 0x02, assert PEEKABOO line */
assign PEEKABOO = opb_oe & (OPB_ABus[3:2] == 2'b01);
/* ... and a write triggers an FPGA reboot */
assign LOAD = opb_we & (OPB_ABus[3:2] == 2'b01);

// this status should have the same form as the status on the cf bus found in StatusAndReset.v
//hrgt: what is the 'dead' for ?
wire [31:0] status = (DcmsLocked    ? `STATUS_DCMS_LOCKED 	 : 0) |
                     (FlashReady    ? `STATUS_FLASH_READY 	 : 0) |
                     (StandaloneSw  ? `STATUS_BACKPLANE_DETECTED : 0) | (32'hdead0000);
wire [31:0] capabilities =
                     (StandaloneSw  ? `IMAGE_CAPABILITIES  | `STATUS_BACKPLANE_DETECTED   //hrgt:12/31/06
                                    : `IMAGE_CAPABILITIES & ~`STATUS_BACKPLANE_DETECTED); //hrgt:12/31/06

assign Sl_DBus[31:0] = 
    opb_oe ?
            ((OPB_ABus[3:2] == 2'b00 ? { 31'h0, opb_flash_en } : 0) | //700000020
             (OPB_ABus[3:2] == 2'b01 ? {  6'h0, FLASH_A[25:0]} : 0) | //700000024 //hrgt: what is this for ??
             (OPB_ABus[3:2] == 2'b10 ? {        status[31:0] } : 0) | //700000028 //hrgt:12/31/06 [31:0]
             (OPB_ABus[3:2] == 2'b11 ? {  capabilities[31:0] } : 0)   //70000002C //hrgt:12/31/06
            ) : 32'h0;

/* Make sure we wait 5 clock cycles to ensure that FLASH_A has enough time to come through */
OPBWait #(.OPB_WAIT_CYCLES(12)) opb_wait(
   .opb_en(opb_en),
   .OPB_Clk(OPB_Clk),
   .OPB_Rst(OPB_Rst),
   .Sl_xferAck(Sl_xferAck)
);

assign Sl_errAck  = 1'b0;
assign Sl_retry   = 1'b0;
assign Sl_toutSup = 1'b0;

assign test_pins[127:0] = 128'h0;

`ifdef ENABLE_DEBUG_TAPS
 wire [100:0] keeper;
 //synthesis attribute KEEP of keeper is TRUE;
 DebugTap #(.Width(32)) OPB_ABus_tap (OPB_ABus[31:0], keeper[0]);
 DebugTap #(.Width(16)) OPB_DBus_tap (OPB_DBus[15:0], keeper[1]);
 DebugTap #(.Width(16)) Sl_DBus_tap (Sl_DBus[15:0], keeper[2]);
 DebugTap #(.Width(4))  OPB_BE_tap (OPB_BE[3:0], keeper[3]);
 DebugTap #(.Width(1))  OPB_select_tap (OPB_select, keeper[4]);
 DebugTap #(.Width(1))  OPB_RNW_tap (OPB_RNW, keeper[5]);
 DebugTap #(.Width(1))  OPB_Clk_tap (OPB_Clk, keeper[6]);
 DebugTap #(.Width(1))  Sl_xferAck_tap (Sl_xferAck, keeper[7]);
 DebugTap #(.Width(1))  opb_en_tap (opb_en, keeper[8]);
 DebugTap #(.Width(2))  OPB_RNWDelay_tap (OPB_RNWDelay, keeper[9]);
 DebugTap #(.Width(1))  MemWait_tap (MemWait, keeper[10]);
 DebugTap #(.Width(1))  DcmsLocked_tap (DcmsLocked, keeper[11]);
 DebugTap #(.Width(1))  FlashReady_tap (FlashReady, keeper[12]);
 DebugTap #(.Width(1))  Standalone_tap (StandaloneSw, keeper[13]);
 DebugTap #(.Width(1))  OpbEnLatch_tap (OpbEnLatch, keeper[14]);
 DebugTap #(.Width(1))  opb_flash_en_tap (opb_flash_en, keeper[15]);
`endif // ENABLE_DEBUG_TAPS

endmodule
